package com.sky.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

/**
 * Spring 对 Redis 客户端进行了整合，提供了 Spring Data Redis，在Spring Boot项目中还提供了对应的Starter，即 spring-boot-starter-data-redis。
 *
 * Redis的通用命令是不分数据类型的，都可以使用的命令：
 * - KEYS pattern 		查找所有符合给定模式( pattern)的 key
 * - EXISTS key 		检查给定 key 是否存在
 * - TYPE key 		返回 key 所储存的值的类型
 * - DEL key 		该命令用于在 key 存在是删除 key
 *
 * Spring Data Redis中提供了一个高度封装的类：RedisTemplate，对相关api进行了归类封装,将同一类型操作封装为operation接口，具体分类如下：
 * - ValueOperations：string数据操作   字符串 string,普通字符串，Redis中最简单的数据类型
 * - SetOperations：set类型数据操作    集合 set,集合(set)：无序集合，没有重复元素，类似于Java中的HashSet
 * - ZSetOperations：zset类型数据操作  有序集合 sorted set / zset,有序集合(sorted set/zset)：集合中每个元素关联一个分数(score)，根据分数升序排序，没有重复元素
 * - HashOperations：hash类型的数据操作   哈希 hash,也叫散列，类似于Java中的HashMap结构
 * - ListOperations：list类型的数据操作   列表 list,列表(list)：按照插入顺序排序，可以有重复元素，类似于Java中的LinkedList
 *
 * Redis 中字符串类型常用命令：
 * - **SET** key value 					         设置指定key的值
 * - **GET** key                                        获取指定key的值
 * - **SETEX** key seconds value         设置指定key的值，并将 key 的过期时间设为 seconds 秒
 * - **SETNX** key value                        只有在 key    不存在时设置 key 的值
 *
 * Redis hash 是一个string类型的 field 和 value 的映射表，hash特别适合用于存储对象，常用命令：
 * - **HSET** key field value             将哈希表 key 中的字段 field 的值设为 value
 * - **HGET** key field                       获取存储在哈希表中指定字段的值
 * - **HDEL** key field                       删除存储在哈希表中的指定字段
 * - **HKEYS** key                              获取哈希表中所有字段
 * - **HVALS** key                              获取哈希表中所有值
 *
 *Redis 列表是简单的字符串列表，按照插入顺序排序，常用命令：
 * - **LPUSH** key value1 [value2]         将一个或多个值插入到列表头部
 * - **LRANGE** key start stop                获取列表指定范围内的元素
 * - **RPOP** key                                       移除并获取列表最后一个元素
 * - **LLEN** key                                        获取列表长度
 * - **BRPOP** key1 [key2 ] timeout       移出并获取列表的最后一个元素， 如果列表没有元素会阻塞列表直到等待超    时或发现可弹出元素为止
 *
 *Redis set 是string类型的无序集合。集合成员是唯一的，这就意味着集合中不能出现重复的数据，常用命令：
 * - **SADD** key member1 [member2]            向集合添加一个或多个成员
 * - **SMEMBERS** key                                         返回集合中的所有成员
 * - **SCARD** key                                                  获取集合的成员数
 * - **SINTER** key1 [key2]                                   返回给定所有集合的交集
 * - **SUNION** key1 [key2]                                 返回所有给定集合的并集
 * - **SREM** key member1 [member2]            移除集合中一个或多个成员
 *
 *Redis有序集合是string类型元素的集合，且不允许有重复成员。每个元素都会关联一个double类型的分数。常用命令：
 * - **ZADD** key score1 member1 [score2 member2]     向有序集合添加一个或多个成员
 * - **ZRANGE** key start stop [WITHSCORES]                     通过索引区间返回有序集合中指定区间内的成员
 * - **ZINCRBY** key increment member                              有序集合中对指定成员的分数加上增量 increment
 * - **ZREM** key member [member ...]                                移除有序集合中的一个或多个成员
 *
 *
 * 1.导入 spring data redis的maven坐标
 * 2.配置redis数据源
 * 3.编写配置类，创建RedisTemplate对象
 * 4.通过RedisTemplate对象操作redis
 */
@Configuration
@Slf4j
//@Component   //加了也报错，Could not autowire. No beans of 'RedisConnectionFactory' type found.
public class RedisConfiguration {
    /**
     * 当前配置类不是必须的，因为 Spring Boot 框架会自动装配 RedisTemplate 对象，但是默认的key序列化器为JdkSerializationRedisSerializer，
     * 导致我们存到Redis中后的数据和原始数据有差别(显示不同)，故设置为StringRedisSerializer序列化器。
     * @param redisConnectionFactory
     * @return
     */

    /**
     * 2024年5月14日21:03:09：无法解决，放弃redis相关联的功能模块(店铺营业状态设置),报错信息在SpringDataRedisTest注释中
     *
     * 2024年5月15日15:44:28，换了jdk问题解决了
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){
        //通过RedisConfiguration配置类，创建RedisTemplate对象（是spring data redis里最核心的最常用的对象）
        log.info("redisTemplate方法开始创建redis模板对象...");
        RedisTemplate redisTemplate = new RedisTemplate();

        //设置redis的连接工厂对象，此处连接工厂对象不需要我们创建，因为在sky-server的pom的引入了starter，starter会把连接工厂对象创建好，放到spring容器中
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        //设置redis key的序列化器(在redis desktop manager里面更好展示key，不然就像key的field或者value一样乱码)
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        return redisTemplate;
    }


}

